package com.alatus.config;

import com.alatus.config.filter.TokenVerifyFilter;
import com.alatus.config.handler.MyAccessDeniedHandler;
import com.alatus.config.handler.MyAuthenticationFailureHandler;
import com.alatus.config.handler.MyAuthenticationSuccessHandler;
import com.alatus.config.handler.MyLogoutSuccessHandler;
import com.alatus.constant.Constants;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;

//开启方法级别的权限检查
@EnableMethodSecurity
@Configuration
public class SecurityConfig {
    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;
    @Resource
    private TokenVerifyFilter tokenVerifyFilter;
//    权限不足
    @Resource
    private MyAccessDeniedHandler myAccessDeniedHandler;

//    配置加密器
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,CorsConfigurationSource configurationSource) throws Exception{
        return httpSecurity
                .formLogin((formLogin) -> {
                    formLogin.loginProcessingUrl((Constants.LOGIN_URI))
                            .usernameParameter("loginAct")
                            .passwordParameter("loginPwd")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailureHandler);
                })
//        SecurityFilterChain改变了默认行为,不再拦截了,需要手动拦截
                .authorizeHttpRequests((authorize) -> {
//                    对任何请求进行拦截,任何请求都需要登录才可以访问
//                    /api/login这个请求放开,其他请求正常拦截
                    authorize.requestMatchers(Constants.LOGIN_URI).permitAll().anyRequest().authenticated();
                })
                .csrf((csrf) -> {
                    //禁用跨站请求伪造
                    csrf.disable();
                })
                //支持跨域请求
                .cors((cors)->{
                    cors.configurationSource(configurationSource);
                })
                .sessionManagement((session) -> {
//                    让session的创建策略为不创建
                    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })
//                添加我们自定义的filter
                .addFilterBefore(tokenVerifyFilter, LogoutFilter.class)
//                退出登录
                .logout((logout) -> {
//                    退出的地址,这个也不需要我们写controller
                    logout.logoutUrl("/api/logOut").logoutSuccessHandler(myLogoutSuccessHandler);
                })
                //无权限时的处理方法
                .exceptionHandling((exceptionHandling) -> {
                    exceptionHandling.accessDeniedHandler(myAccessDeniedHandler);
                })
                .build();
    }
    @Bean
    public CorsConfigurationSource configurationSource(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));//允许任意来源
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));//允许任意方法请求
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));//允许请求头任意内容
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        任何路径都按这个来
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }
}
